home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / resolv / res_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-28  |  12.9 KB  |  440 lines

  1. /*
  2.  * ++Copyright++ 1985, 1989, 1993
  3.  * -
  4.  * Copyright (c) 1985, 1989, 1993
  5.  *    The Regents of the University of California.  All rights reserved.
  6.  * 
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. All advertising materials mentioning features or use of this software
  16.  *    must display the following acknowledgement:
  17.  *     This product includes software developed by the University of
  18.  *     California, Berkeley and its contributors.
  19.  * 4. Neither the name of the University nor the names of its contributors
  20.  *    may be used to endorse or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  * 
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  * -
  35.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  36.  * 
  37.  * Permission to use, copy, modify, and distribute this software for any
  38.  * purpose with or without fee is hereby granted, provided that the above
  39.  * copyright notice and this permission notice appear in all copies, and that
  40.  * the name of Digital Equipment Corporation not be used in advertising or
  41.  * publicity pertaining to distribution of the document or software without
  42.  * specific, written prior permission.
  43.  * 
  44.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  45.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  46.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  47.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  48.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  49.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  50.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  51.  * SOFTWARE.
  52.  * -
  53.  * --Copyright--
  54.  */
  55.  
  56. #if defined(LIBC_SCCS) && !defined(lint)
  57. static char sccsid[] = "@(#)res_init.c    8.1 (Berkeley) 6/7/93";
  58. static char rcsid[] = "$Id: res_init.c,v 1.2 1994/07/28 21:56:23 roland Exp $";
  59. #endif /* LIBC_SCCS and not lint */
  60.  
  61. #include <sys/param.h>
  62. #include <sys/socket.h>
  63. #include <netinet/in.h>
  64. #include <arpa/inet.h>
  65. #include <arpa/nameser.h>
  66.  
  67. #include <stdio.h>
  68. #include <ctype.h>
  69. #include <resolv.h>
  70. #if defined(BSD) && (BSD >= 199103)
  71. # include <unistd.h>
  72. # include <stdlib.h>
  73. # include <string.h>
  74. #else
  75. # include "../conf/portability.h"
  76. #endif
  77.  
  78. #if defined(USE_OPTIONS_H)
  79. # include "../conf/options.h"
  80. #endif
  81.  
  82. static void res_setoptions __P((char *, char *));
  83.  
  84. #ifdef RESOLVSORT
  85. static u_int32_t net_mask __P((struct in_addr));
  86. #endif
  87.  
  88. #if !defined(isascii)    /* XXX - could be a function */
  89. # define isascii(c) (!(c & 0200))
  90. #endif
  91.  
  92. /*
  93.  * Resolver state default settings.
  94.  */
  95.  
  96. struct __res_state _res;
  97.  
  98. /*
  99.  * Set up default settings.  If the configuration file exist, the values
  100.  * there will have precedence.  Otherwise, the server address is set to
  101.  * INADDR_ANY and the default domain name comes from the gethostname().
  102.  *
  103.  * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
  104.  * rather than INADDR_ANY ("0.0.0.0") as the default name server address
  105.  * since it was noted that INADDR_ANY actually meant ``the first interface
  106.  * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
  107.  * it had to be "up" in order for you to reach your own name server.  It
  108.  * was later decided that since the recommended practice is to always 
  109.  * install local static routes through 127.0.0.1 for all your network
  110.  * interfaces, that we could solve this problem without a code change.
  111.  *
  112.  * The configuration file should always be used, since it is the only way
  113.  * to specify a default domain.  If you are running a server on your local
  114.  * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
  115.  * in the configuration file.
  116.  *
  117.  * Return 0 if completes successfully, -1 on error
  118.  */
  119. res_init()
  120. {
  121.     register FILE *fp;
  122.     register char *cp, **pp;
  123.     register int n, dots;
  124.     char buf[BUFSIZ];
  125.     int nserv = 0;    /* number of nameserver records read from file */
  126.     int haveenv = 0;
  127.     int havesearch = 0;
  128. #ifdef RESOLVSORT
  129.     int nsort = 0;
  130.     char *net;
  131. #endif
  132.  
  133.     /*
  134.      * These four fields used to be statically initialized.  This made
  135.      * it hard to use this code in a shared library.  It is necessary,
  136.      * now that we're doing dynamic initialization here, that we preserve
  137.      * the old semantics: if an application modifies one of these three
  138.      * fields of _res before res_init() is called, res_init() will not
  139.      * alter them.  Of course, if an application is setting them to
  140.      * _zero_ before calling res_init(), hoping to override what used
  141.      * to be the static default, we can't detect it and unexpected results
  142.      * will follow.  Zero for any of these fields would make no sense,
  143.      * so one can safely assume that the applications were already getting
  144.      * unexpected results.
  145.      */
  146.     if (!_res.retrans)
  147.         _res.retrans = RES_TIMEOUT;
  148.     if (!_res.retry)
  149.         _res.retry = 4;
  150.     if (!_res.options)
  151.         _res.options = RES_DEFAULT;
  152.  
  153. #ifdef USELOOPBACK
  154.     _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
  155. #else
  156.     _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
  157. #endif
  158.     _res.nsaddr.sin_family = AF_INET;
  159.     _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
  160.     _res.nscount = 1;
  161.     _res.ndots = 1;
  162.     _res.pfcode = 0;
  163.  
  164.     /* Allow user to override the local domain definition */
  165.     if ((cp = getenv("LOCALDOMAIN")) != NULL) {
  166.         (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
  167.         haveenv++;
  168.  
  169.         /*
  170.          * Set search list to be blank-separated strings
  171.          * from rest of env value.  Permits users of LOCALDOMAIN
  172.          * to still have a search list, and anyone to set the
  173.          * one that they want to use as an individual (even more
  174.          * important now that the rfc1535 stuff restricts searches)
  175.          */
  176.         cp = _res.defdname;
  177.         pp = _res.dnsrch;
  178.         *pp++ = cp;
  179.         for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
  180.             if (*cp == '\n')    /* silly backwards compat */
  181.                 break;
  182.             else if (*cp == ' ' || *cp == '\t') {
  183.                 *cp = 0;
  184.                 n = 1;
  185.             } else if (n) {
  186.                 *pp++ = cp;
  187.                 n = 0;
  188.                 havesearch = 1;
  189.             }
  190.         }
  191.         /* null terminate last domain if there are excess */
  192.         while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
  193.             cp++;
  194.         *cp = '\0';
  195.         *pp++ = 0;
  196.     }
  197.  
  198.     if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
  199.         /* read the config file */
  200.         while (fgets(buf, sizeof(buf), fp) != NULL) {
  201.         /* skip comments */
  202.         if ((*buf == ';') || (*buf == '#'))
  203.             continue;
  204.         /* read default domain name */
  205.         if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
  206.             if (haveenv)    /* skip if have from environ */
  207.                 continue;
  208.             cp = buf + sizeof("domain") - 1;
  209.             while (*cp == ' ' || *cp == '\t')
  210.                 cp++;
  211.             if ((*cp == '\0') || (*cp == '\n'))
  212.                 continue;
  213.             (void)strncpy(_res.defdname, cp,
  214.                   sizeof(_res.defdname) - 1);
  215.             if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
  216.                 *cp = '\0';
  217.             havesearch = 0;
  218.             continue;
  219.         }
  220.         /* set search list */
  221.         if (!strncmp(buf, "search", sizeof("search") - 1)) {
  222.             if (haveenv)    /* skip if have from environ */
  223.                 continue;
  224.             cp = buf + sizeof("search") - 1;
  225.             while (*cp == ' ' || *cp == '\t')
  226.                 cp++;
  227.             if ((*cp == '\0') || (*cp == '\n'))
  228.                 continue;
  229.             (void)strncpy(_res.defdname, cp,
  230.                   sizeof(_res.defdname) - 1);
  231.             if ((cp = strchr(_res.defdname, '\n')) != NULL)
  232.                 *cp = '\0';
  233.             /*
  234.              * Set search list to be blank-separated strings
  235.              * on rest of line.
  236.              */
  237.             cp = _res.defdname;
  238.             pp = _res.dnsrch;
  239.             *pp++ = cp;
  240.             for (n = 0;
  241.              *cp && pp < _res.dnsrch + MAXDNSRCH;
  242.              cp++) {
  243.                 if (*cp == ' ' || *cp == '\t') {
  244.                     *cp = 0;
  245.                     n = 1;
  246.                 } else if (n) {
  247.                     *pp++ = cp;
  248.                     n = 0;
  249.                 }
  250.             }
  251.             /* null terminate last domain if there are excess */
  252.             while (*cp != '\0' && *cp != ' ' && *cp != '\t')
  253.                 cp++;
  254.             *cp = '\0';
  255.             *pp++ = 0;
  256.             havesearch = 1;
  257.             continue;
  258.         }
  259.         /* read nameservers to query */
  260.         if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
  261.            nserv < MAXNS) {
  262.            struct in_addr a;
  263.  
  264.             cp = buf + sizeof("nameserver") - 1;
  265.             while (*cp == ' ' || *cp == '\t')
  266.             cp++;
  267.             if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
  268.             _res.nsaddr_list[nserv].sin_addr = a;
  269.             _res.nsaddr_list[nserv].sin_family = AF_INET;
  270.             _res.nsaddr_list[nserv].sin_port =
  271.                 htons(NAMESERVER_PORT);
  272.             nserv++;
  273.             }
  274.             continue;
  275.         }
  276. #ifdef RESOLVSORT
  277.         if (!strncmp(buf, "sortlist", sizeof("sortlist") -1)) {
  278.             struct in_addr a;
  279.  
  280.             cp = buf + sizeof("sortlist") - 1;
  281.             while (nsort < MAXRESOLVSORT) {
  282.             while (*cp == ' ' || *cp == '\t')
  283.                 cp++;
  284.             if (*cp == '\0' || *cp == '\n' || *cp == ';')
  285.                 break;
  286.             net = cp;
  287.             while (*cp && *cp != '/' &&
  288.                 isascii(*cp) && !isspace(*cp))
  289.                 cp++;
  290.             n = *cp;
  291.             *cp = 0;
  292.             if (inet_aton(net, &a)) {
  293.                 _res.sort_list[nsort].addr = a;
  294.                 if (n == '/') {
  295.                 *cp++ = n;
  296.                 net = cp;
  297.                 while (*cp && isascii(*cp) && !isspace(*cp))
  298.                     cp++;
  299.                 n = *cp;
  300.                 *cp = 0;
  301.                 if (inet_aton(net, &a)) {
  302.                     _res.sort_list[nsort].mask = a.s_addr;
  303.                 } else {
  304.                     _res.sort_list[nsort].mask = 
  305.                     net_mask(_res.sort_list[nsort].addr);
  306.                 }
  307.                 } else {
  308.                 _res.sort_list[nsort].mask = 
  309.                     net_mask(_res.sort_list[nsort].addr);
  310.                 }
  311.                 nsort++;
  312.             }
  313.             *cp++ = n;
  314.             }
  315.             continue;
  316.         }
  317. #endif
  318.         if (!strncmp(buf, "options", sizeof("options") -1)) {
  319.             res_setoptions(buf + sizeof("options") - 1, "conf");
  320.             continue;
  321.         }
  322.         }
  323.         if (nserv > 1) 
  324.         _res.nscount = nserv;
  325. #ifdef RESOLVSORT
  326.         _res.nsort = nsort;
  327. #endif
  328.         (void) fclose(fp);
  329.     } /*if(fopen)*/
  330.     if (_res.defdname[0] == 0) {
  331.         if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
  332.            (cp = strchr(buf, '.'))) {
  333.             (void)strcpy(_res.defdname, cp + 1);
  334.         }
  335.     }
  336.  
  337.     /* find components of local domain that might be searched */
  338.     if (havesearch == 0) {
  339.         pp = _res.dnsrch;
  340.         *pp++ = _res.defdname;
  341.         *pp = NULL;
  342.  
  343. #ifndef RFC1535
  344.         dots = 0;
  345.         for (cp = _res.defdname;  *cp;  cp++)
  346.             dots += (*cp == '.');
  347.  
  348.         cp = _res.defdname;
  349.         while (pp < _res.dnsrch + MAXDFLSRCH) {
  350.             if (dots < LOCALDOMAINPARTS) {
  351.                 break;
  352.             }
  353.             cp = strchr(cp, '.') + 1;    /* we know there is one */
  354.             *pp++ = cp;
  355.             dots--;
  356.         }
  357.         *pp = NULL;
  358. #ifdef DEBUG
  359.         if (_res.options & RES_DEBUG) {
  360.             printf(";; res_init()... default dnsrch list:\n");
  361.             for (pp = _res.dnsrch;  *pp;  pp++) {
  362.                 printf(";;\t%s\n", *pp);
  363.             }
  364.             printf(";;\t..END..\n");
  365.         }
  366. #endif /*DEBUG*/
  367. #endif /*!RFC1535*/
  368.     }
  369.  
  370.     if ((cp = getenv("RES_OPTIONS")) != NULL) {
  371.         res_setoptions(cp, "env");
  372.     }
  373.     _res.options |= RES_INIT;
  374.     return (0);
  375. }
  376.  
  377.  
  378. static void
  379. res_setoptions(options, source)
  380.     char *options, *source;
  381. {
  382.     char *cp = options;
  383.     int i;
  384.  
  385. #ifdef DEBUG
  386.     if (_res.options & RES_DEBUG) {
  387.         printf(";; res_setoptions(\"%s\", \"%s\")...\n",
  388.                options, source);
  389.     }
  390. #endif
  391.     while (*cp) {
  392.         /* skip leading and inner runs of spaces */
  393.         while (*cp == ' ' || *cp == '\t')
  394.             cp++;
  395.         /* search for and process individual options */
  396.         if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) {
  397.             i = atoi(cp + sizeof("ndots:") - 1);
  398.             if (i <= RES_MAXNDOTS)
  399.                 _res.ndots = i;
  400.             else
  401.                 _res.ndots = RES_MAXNDOTS;
  402. #ifdef DEBUG
  403.             if (_res.options & RES_DEBUG) {
  404.                 printf(";;\tndots=%d\n", _res.ndots);
  405.             }
  406. #endif
  407.         } else if (!strncmp(cp, "debug", sizeof("debug")-1)) {
  408. #ifdef DEBUG
  409.             if (!(_res.options & RES_DEBUG)) {
  410.                 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
  411.                        options, source);
  412.                 _res.options |= RES_DEBUG;
  413.             }
  414.             printf(";;\tdebug\n");
  415. #endif
  416.         } else {
  417.             /* XXX - print a warning here? */
  418.         }
  419.         /* skip to next run of spaces */
  420.         while (*cp && *cp != ' ' && *cp != '\t')
  421.             cp++;
  422.     }
  423. }
  424.  
  425. #ifdef RESOLVSORT
  426. static u_int32_t
  427. net_mask(in)        /* XXX - should really use system's version of this */
  428.     struct in_addr in;
  429. {
  430.         register u_int32_t i = ntohl(in.s_addr);
  431.  
  432.         if (IN_CLASSA(i))
  433.                 return (htonl(IN_CLASSA_NET));
  434.         else if (IN_CLASSB(i))
  435.                 return (htonl(IN_CLASSB_NET));
  436.         else
  437.                 return (htonl(IN_CLASSC_NET));
  438. }
  439. #endif
  440.